package com.hqyj.filter;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hqyj.pojo.CodeEnum;
import com.hqyj.pojo.R;
import com.hqyj.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;

import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * jwt权限认证
 */
@Slf4j
@Component
public class JwtFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求的request对象
        ServerHttpRequest request = exchange.getRequest();
        //获取响应对象response
        ServerHttpResponse response = exchange.getResponse();
        log.info("-------------请求是否放行---------------");
        //设置那些链接需要放行
        String url[] = {
                "/server-login/user-info/user",
                "/server-goods-info/goods-info/goods",
                "/server-goods-info/goods-info/goods/1",
                "/server-goods-info/goods-info/goods/2",
                "/server-register/userInfo/user",
                "/server-buy-car/buyCar/car",
                "/server-goods-info/order/order",
        };
        //获取请求的地址
        String rqUrl = request.getPath().value();
        //判断请求的地址是否在放行的地址里
        boolean is = false;
        for(String u:url){
            if(rqUrl.equals(u)){
                    is= true;
            }
        }
        if(is==true){
            log.info("请求放行");
            //放行
            return chain.filter(exchange);
        }
        log.info("------------验证token业务---------------");
        //获取token值
        String token = request.getHeaders().getFirst("Authorization");
        // 判断token是否为空
        if(StringUtils.isEmpty(token)){
            log.info("token为空");
            //设置返回响应结果信息给前端
            ObjectMapper mapper = new ObjectMapper();
            DataBuffer data =null;
            try {
                 data = response.bufferFactory().wrap(mapper.writeValueAsBytes(R.error("token为空",CodeEnum.POWER.CODE,null)));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return response.writeWith(Mono.just(data));
        }
        //获取用户的id,来判断token是否正确
        String id = JwtUtil.getAudience(token);
        if(id==null){
            log.info("token不正确");
            //设置返回响应结果信息给前端
            ObjectMapper mapper = new ObjectMapper();
            DataBuffer data =null;
            try {
                data = response.bufferFactory().wrap(mapper.writeValueAsBytes(R.error("token不正确",CodeEnum.POWER.CODE,null)));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            return response.writeWith(Mono.just(data));
        }

        log.info("验证token是超时");
        //获取盐值
        String salt = JwtUtil.getClaimByName(token,"jwtSalt").asString();
        //验证 token 是否正确
        DecodedJWT obj = JwtUtil.verifyToken(token,salt);
        if(obj==null){
            log.info("token超时");
            //设置返回响应结果信息给前端
            ObjectMapper mapper = new ObjectMapper();
            DataBuffer data =null;
            try {
                data = response.bufferFactory().wrap(mapper.writeValueAsBytes(R.error("token超时",CodeEnum.POWER.CODE,null)));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            return response.writeWith(Mono.just(data));
        }
        //验证通过，放行
        return chain.filter(exchange);
    }

    //设置过滤器优先级 ，return 返回的数值越小，优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}
